package com.keepers.repair.tcp;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import com.keepers.repair.net.LogUtil;
import com.keepers.repair.tcp.utils.LoopBuffer;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 设置连接参数
 */

public class TCPClient {
    /**
     * 服务器ip
     */
    private String mServerIp;
    /**
     * 服务器端口号
     */
    private int    mServerPort;
    /**
     * 连接超时时间 默认设置为10s
     */
    private int mConnTimeout = 10 * 1000;
    /**
     * 心跳数据
     */
    private        byte[]           mBreath;
    /**
     * 心跳间隔时间
     */
    private        int              mBreathTime;
    private static TCPClient        client;
    private        byte[]           sendData;
    private        ResponseCallback responseCallback;

    private        Thread thread;
    private static Socket socket;

    public boolean isConnectServerInner;

//    private DataInputStream dis;

    private TCPClient() {
    }

    /**
     * 获取TCPClient的实例
     *
     * @return
     */
    public static TCPClient build() {
        if (client == null) {
            synchronized (TCPClient.class) {
                if (client == null) {
                    client = new TCPClient();
                }
            }
        }
        return client;
    }

    private static final int SOCKET_OK       = 10003;
    private static final int RE_CONN_SUCCESS = 10005;

    private Handler mHandler = new Handler(Looper.myLooper()) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case SOCKET_OK:
                    //发送数据
                    request();
                    break;
                case RE_CONN_SUCCESS:
                    //开启接收数据
                    receive();
                    sendBreadth();
                    break;
            }
        }
    };

    /**
     * 设置目标服务器的ip和端口号
     *
     * @param ip   ip地址
     * @param port 端口号
     * @return
     */
    public TCPClient server(String ip, int port) {
        mServerIp = ip;
        mServerPort = port;
        return this;
    }

    /**
     * 设置连接超时时间
     *
     * @param connTimeout 连接超时时间
     * @return
     */
    public TCPClient connTimeout(int connTimeout) {
        mConnTimeout = connTimeout;
        return this;
    }

    /**
     * 设置心跳数据
     *
     * @param breath     心跳内容
     * @param breathTime 心跳间隔时间
     * @return
     */
    public TCPClient breath(byte[] breath, int breathTime) {
        mBreath = breath;
        mBreathTime = breathTime;
        return this;
    }

    //----------------------发送数据：判断连接是否存在；连接存在 则直接发送数据，连接不存在，尝试进行连接，连接成功发送数据

    /**
     * 发送请求到服务器
     *
     * @param data 数据
     */
    public synchronized void request(byte[] data) {
        sendData = data;
        request();
    }
    //----------------------接收数据：判断连接是否存在；连接存在 则不进行操作，连接不存在，尝试进行连接，连接成功接收数据

    /**
     * 接收数据
     *
     * @param responseCallBack 建立连接接收数据 接收数据
     */
    public void onResponse(ResponseCallback responseCallBack) {
        this.responseCallback = responseCallBack;
        connectServerInner();
    }


    /**
     * 关闭当前连接
     */
    public void closeTcp() {
        if (isConnectServerInner) {
            return;
        }
        try {
            if (socket != null) {
                Log.e("aa", " closeTcp ");
                socket.close();
                socket = null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 开启线程连接服务器
     */
    private void connectServerInner() {
        String serverNo = mServerIp + mServerPort;
        if (thread != null && serverNo.equals(thread.getName())) {
            return;
        }
        isConnectServerInner = true;
        thread = new Thread(() -> {
            try {
                if (socket != null) {
                    LogUtil.e("connectServerInner closeTcp ");
                    socket.close();
                    socket = null;
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                socket = new Socket(mServerIp, mServerPort);
//                socket.setSoTimeout(10 * 1000);//设置读取超时时间
                // 设置此套接字的性能偏好 低延迟2>连接时间1>高带宽0
                socket.setKeepAlive(true);
                socket.setPerformancePreferences(1, 2, 0);
//                socket.connect(new InetSocketAddress(mServerIp, mServerPort), mConnTimeout);
                //连接服务器成功
                LogUtil.e("连接成功 connectServerInner  mServerIp = " + mServerIp + " mServerPort = " + mServerPort);
                mHandler.sendEmptyMessage(RE_CONN_SUCCESS);
            } catch (IOException e) {
                LogUtil.e("connectServerInner 链接失败");
                e.printStackTrace();
                onFail(e);
            } finally {
                isConnectServerInner = false;
            }
            thread = null;
        }, mServerIp + mServerPort);
        thread.start();
//        connectSocketReceiveCheckTimer();
    }

    /**
     * 内部处理：发送心跳
     */
    private void sendBreadth() {
        if (mBreath == null) {
            return;
        }
        new Thread(() -> {
            while (isConnected()) {
                try {
                    OutputStream os = socket.getOutputStream();
                    Log.e("aa", "发送心跳");
                    os.write(mBreath);//发送心跳
                    os.flush();
                    socket.sendUrgentData(0xff);
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.e("aa", "发送心跳异常 = " + e.getMessage());
                    if (!isConnectServerInner) {
                        connectServerInner();
                    }
                }
                try {
                    Thread.sleep(mBreathTime);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }


    public void connectSocketReceiveCheckTimer() {
        Timer timer = new Timer();
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                boolean connected = isConnected();
                LogUtil.e("_SPI_FIX connectSocketReceiveCheckTimer.run()-S-connectSocketReceived: " + connected + " isConnectServerInner " + isConnectServerInner);
                if (!connected && !isConnectServerInner) {
                    connectServerInner();
                }
                LogUtil.e("_SPI_FIX connectSocketReceiveCheckTimer.run()-E-connectSocketReceivedAccount: " + connected + " isConnectServerInner " + isConnectServerInner);
            }
        };
        timer.schedule(task, 5000);
    }

    /**
     * 内部处理：发送请求
     */
    private synchronized void request() {
        try {
            if (isConnected()) {
                OutputStream os = socket.getOutputStream();
                if (sendData != null) {
                    os.write(sendData);//发送请求
                    os.flush();
                }
            }
        } catch (IOException e) {
            LogUtil.e("request 发送数据错误 e：" + e.getMessage());
            e.printStackTrace();
            onFail(e);
        }
    }

    /**
     * 内部处理：接收数据
     */
    private void receive() {
        new Thread(() -> {
            while (isConnected()) {
                if (socket == null) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    continue;
                }
//                    if (dis == null) {
//                        LogUtil.e("aa", "--------------- DataInputStream");
//                        connectServerInner();
//                        return;
//                    }

//                    int len;
//                    byte[] buf = new byte[4096];
//                    String receive = "";
                try {
//                        LogUtil.e("aa", "---------------");
//                        if ((len = dis.read(buf)) > 0) {
//                            receive = new String(buf, 0, len);
//                            LogUtil.e(" receivePacketCount: " + receive + " len:" + len);
//                        }
//                        dis = new DataInputStream(socket.getInputStream());
//                        String[] split = receive.split("\r\n");
//                        LogUtil.e("aa", "---------------2");
//                        for (String s : split) {
//                            String msg = UtilsKt.decodeBase64(s);
//                            LogUtil.e("接收消息：" + msg);
//                            if (responseCallback != null) {
//                                responseCallback.onRec(msg);
//                            }
//                        }

                    InputStream is = socket.getInputStream();
                    byte[] data = new byte[4096];
//                    int len;
//                    if ((len = is.read(data)) > 0) {
//                        LogUtil.e(" receivePacketCount: " + len + " len:" + len);
//                    }
                    int len = is.read(data);
                    if (len == -1) {
                        continue;
                    }
                    LogUtil.e(" receivePacketCount: " + len);
                    byte[] newData = new byte[len];
                    System.arraycopy(data, 0, newData, 0, len);
                    LoopBuffer.getInstance().write(newData);
                    if (responseCallback != null) {
                        responseCallback.onRec();
                    }
                } catch (IOException e) {
                    LogUtil.e(" DataInputStream.SocketException:" + e.getMessage());
                    if (!TextUtils.isEmpty(e.getMessage())) {
                        if (!isConnectServerInner) {
                            connectServerInner();
                        }
                    }
                }
            }
        }).start();
    }


    public boolean isConnected() {
        return socket != null && socket.isConnected() && !socket.isClosed();
    }

//    /**
//     * 判断网络是否打开的操作
//     */
//    private void isServerOpen() {
//        //查看指定服务器是否已经连接
//        if (socket != null) {
//            Message message = mHandler.obtainMessage();
//            message.what = SOCKET_OK;
//            message.obj = socket;
//            mHandler.sendMessage(message);
//        } else {
//            Message message = mHandler.obtainMessage();
//            message.what = SOCKET_CLOSED;
//            mHandler.sendMessage(message);
//        }
//    }

    private void onFail(Throwable e) {
        if (responseCallback != null) {
            responseCallback.onFail(e);
        }
    }
}
